<template>
  <div class="operation-log-page">
    <span class="main-page-title"><strong>&nbsp;操作日志</strong></span>
    <div class="main-card operation-log-card">
      <div class="operation-log-header">
        <div class="header-left">
          <div class="date-filter-group-nogap">
            <span class="filter-label-nogap">操作时间</span>
            <el-date-picker
              v-model="dateRange"
              type="daterange"
              range-separator="-"
              start-placeholder="开始日期"
              end-placeholder="结束日期"
              format="YYYY/MM/DD"
              value-format="YYYY-MM-DD"
              class="date-range-picker-nogap"
              @change="handleDateChange"
            />
          </div>
          <div class="module-filter-group-nogap" style="margin-left: 24px">
            <span class="filter-label-nogap">操作模块</span>
            <el-select
              v-model="selectedModule"
              placeholder="全部"
              clearable
              class="select-nogap"
              @change="handleModuleChange"
            >
              <el-option
                v-for="item in moduleList"
                :key="item"
                :label="item"
                :value="item"
              />
            </el-select>
          </div>
        </div>
        <div class="header-right">
          <el-input
            v-model="keyword"
            placeholder="请输入昵称和手机号进行搜索"
            class="search-input"
            clearable
            @keyup.enter="handleSearch"
            style="width: 260px"
          >
            <template #append>
              <el-button @click="handleSearch" class="search-btn-blue">
                <el-icon><Search /></el-icon>
              </el-button>
            </template>
          </el-input>
        </div>
      </div>
      <div class="table-header-rect-big">
        <div class="table-header-row-flex">
          <div class="table-header-cell-flex first">用户昵称</div>
          <div class="table-header-cell-flex">手机号</div>
          <div class="table-header-cell-flex">操作模块</div>
          <div class="table-header-cell-flex">操作项</div>
          <div class="table-header-cell-flex" style="cursor:pointer; user-select:none;">
            操作时间
            <span class="sort-icons">
              <span
                class="triangle"
                :class="sortOrder === 'ascend' ? 'active' : ''"
                @click.stop="setSort('ascend')"
              >▲</span>
              <span
                class="triangle"
                :class="sortOrder === 'descend' ? 'active' : ''"
                @click.stop="setSort('descend')"
              >▼</span>
            </span>
          </div>
        </div>
      </div>
      <el-table
        :data="logList"
        style="width: 100%; margin-top: 0"
        :border="false"
        class="custom-table"
        :show-header="false"
        @sort-change="handleSortChange"
      >
        <el-table-column align="left">
          <template #default="scope">
            <div class="table-row-flex">
              <div class="table-cell-flex first">
                <div class="user-cell">
                  <img
                    v-if="scope.row.userAvatar"
                    :src="scope.row.userAvatar"
                    class="avatar-img-square left"
                    alt="头像"
                  />
                  <span class="nickname-text">{{ scope.row.userName }}</span>
                </div>
              </div>
              <div class="table-cell-flex">{{ scope.row.userMobile }}</div>
              <div class="table-cell-flex">{{ scope.row.operateModule }}</div>
              <div class="table-cell-flex">{{ scope.row.operate }}</div>
              <div class="table-cell-flex">{{ scope.row.createdAt }}</div>
            </div>
          </template>
        </el-table-column>
        <el-table-column
          prop="createdAt"
          label="操作时间"
          sortable="custom"
          v-if="false" />
      </el-table>
      <div class="pagination-bar">
        <el-pagination
          background
          layout="total, sizes, prev, pager, next"
          :total="total"
          :page-size="pageSize"
          :current-page="currentPage"
          :page-sizes="[10, 20, 50, 100]"
          @current-change="handlePageChange"
          @size-change="handleSizeChange"
        />
      </div>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { ref, onMounted } from "vue";
import { ElMessage } from "element-plus";
import { getOptLogListByPage, getModuleDropdownList } from "@/api/log";
import type {
  GetOptLogListByPageParams,
  LogListItem,
  GetModuleDropdownListResponseData,
} from "@/api/model/model";
import { Search } from "@element-plus/icons-vue";

const logList = ref<LogListItem[]>([]);
const total = ref(0);
const pageSize = ref(10);
const currentPage = ref(1);
const keyword = ref("");
const dateRange = ref<[string, string] | null>(null);
const selectedModule = ref<string | undefined>(undefined);
const moduleList = ref<GetModuleDropdownListResponseData>([]);
const loading = ref(false);
const orderBy = ref('');
const sortOrder = ref('');

const fetchModuleList = async () => {
  try {
    const res = await getModuleDropdownList();
    if (res.data.code === "100") {
      moduleList.value = res.data.data || [];
    }
  } catch {
    // ignore
  }
};

const fetchLogList = async () => {
  loading.value = true;
  try {
    const params: GetOptLogListByPageParams = {
      page: String(currentPage.value),
      pageSize: String(pageSize.value),
      keyword: keyword.value.trim() || undefined,
      module: selectedModule.value || undefined,
      orderBy: orderBy.value || JSON.stringify({ field: "createdAt", order: "descend" }),
    };
    if (dateRange.value && (dateRange.value as [string, string]).length === 2) {
      params.startDate = (dateRange.value as [string, string])[0];
      params.endDate = (dateRange.value as [string, string])[1];
    }
    const res = await getOptLogListByPage(params);
    if (res.data.code === "100") {
      const data = res.data.data;
      logList.value = data.list || [];
      total.value = data.total || 0;
    } else {
      ElMessage.warning(res.data.message || "获取日志失败");
    }
  } catch {
    ElMessage.error("获取日志失败");
  } finally {
    loading.value = false;
  }
};

const handlePageChange = (page: number) => {
  currentPage.value = page;
  fetchLogList();
};
const handleSizeChange = (size: number) => {
  pageSize.value = size;
  currentPage.value = 1;
  fetchLogList();
};
const handleSearch = () => {
  currentPage.value = 1;
  fetchLogList();
};
const handleDateChange = (val: [string, string] | null) => {
  dateRange.value = val;
};
const handleModuleChange = () => {
  currentPage.value = 1;
  fetchLogList();
};

function handleSortChange({ prop, order }: { prop: string; order: string }) {
  let realOrder = '';
  if (order === 'ascending') realOrder = 'ascend';
  else if (order === 'descending') realOrder = 'descend';
  else realOrder = order;
  if (realOrder) {
    orderBy.value = JSON.stringify({ field: prop, order: realOrder });
  } else {
    orderBy.value = '';
  }
  currentPage.value = 1;
  fetchLogList();
}

function setSort(order: string) {
  if (sortOrder.value === order) {
    sortOrder.value = '';
  } else {
    sortOrder.value = order;
  }
  handleSortChange({ prop: 'createdAt', order: sortOrder.value });
}

onMounted(() => {
  fetchModuleList();
  fetchLogList();
});
</script>

<style scoped>
.operation-log-page {
  background: #f5f6fa;
  min-height: 100vh;
  margin: 16px 0 0 0;
  padding: 16px 24px 0 24px;
  display: block;
}
.main-page-title {
  font-size: 20px;
  font-weight: bold;
  color: #222;
  margin-bottom: 24px;
  margin-left: 0;
  text-align: left;
  position: relative;
  top: -16px;
  display: block;
  width: auto;
}
.main-card, .operation-log-card {
  width: 90%;
  margin: 0 auto 32px auto;
  background: #fff;
  border-radius: 14px;
  box-shadow: 0 4px 24px rgba(0, 0, 0, 0.08);
  padding: 32px 36px 24px 36px;
  position: relative;
  top: -16px;
}
.operation-log-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 24px 32px 0 32px;
  background: #fff;
  border-radius: 12px 12px 0 0;
}
.header-left {
  display: flex;
  align-items: center;
  margin-left: -32px;
}
.header-right {
  display: flex;
  align-items: center;
}
.filter-label-nogap {
  height: 32px;
  width: 110px;
  font-size: 15px;
  border-radius: 4px 0 0 4px;
  background: #f5f6fa;
  border: 1px solid #e6e6e6;
  border-right: none;
  display: flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  line-height: 32px;
}
.date-range-picker-nogap {
  height: 32px;
  border-radius: 0 4px 4px 0;
  border: 1px solid #e6e6e6;
  border-left: none;
  width: 90px;
  display: flex;
  align-items: center;
  box-sizing: border-box;
  line-height: 32px;
}
.search-btn-blue {
  background: #1677ff !important;
  border: 1px solid #1677ff !important;
  border-radius: 0 4px 4px 0 !important;
  color: #fff !important;
  width: 48px !important;
  min-width: 48px !important;
  height: 32px !important;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.2s;
}
.search-btn-blue:hover {
  background: #0958d9 !important;
  border-color: #0958d9 !important;
}
.table-header-rect-big {
  width: 100%;
  background: #f5f6fa;
  border-radius: 8px;
  margin-bottom: 0;
  margin-top: 16px;
  box-sizing: border-box;
  padding: 0 0;
}
.table-header-row-flex {
  display: flex;
  flex-direction: row;
  align-items: center;
  height: 48px;
  border-radius: 8px;
  overflow: hidden;
}
.table-header-cell-flex {
  flex: 1 1 0;
  text-align: left;
  font-size: 15px;
  color: #222;
  font-weight: 500;
  background: #f5f6fa;
  height: 48px;
  display: flex;
  align-items: center;
  padding: 0 16px;
  box-sizing: border-box;
}
.table-header-cell-flex.first {
  padding-left: 16px;
}
.table-row-flex {
  display: flex;
  flex-direction: row;
  align-items: center;
  min-height: 48px;
}
.table-cell-flex {
  flex: 1 1 0;
  text-align: left;
  display: flex;
  align-items: center;
  padding: 0 16px;
  min-height: 48px;
  box-sizing: border-box;
}
.table-cell-flex.first {
  padding-left: 16px;
}
.avatar-img-square.left {
  margin-right: 16px;
  margin-left: 0;
  width: 36px;
  height: 36px;
  object-fit: cover;
  border: 1px solid #e6e6e6;
  border-radius: 4px;
}
.nickname-text {
  font-size: 16px;
  color: #222;
  font-weight: 500;
  margin-left: 0;
}
.custom-table ::v-deep(.el-table__body-wrapper) table {
  border-collapse: separate !important;
  border-spacing: 0;
}
.custom-table ::v-deep(.el-table__body-wrapper td),
.custom-table ::v-deep(.el-table__header-wrapper th) {
  border-right: none !important;
}
.custom-table ::v-deep(.el-table__body-wrapper tr) {
  border-bottom: 1px solid #ebeef5 !important;
}
.custom-table ::v-deep(.el-table__body-wrapper td) {
  border-bottom: 1px solid #ebeef5 !important;
}
.custom-table ::v-deep(.el-table__header-wrapper th) {
  border-bottom: 1px solid #ebeef5 !important;
}
.custom-table ::v-deep(.el-table__body-wrapper td:last-child),
.custom-table ::v-deep(.el-table__header-wrapper th:last-child) {
  border-right: none !important;
}
.pagination-bar {
  margin: 24px 0 0 0;
  display: flex;
  justify-content: flex-end;
  padding-right: 32px;
}
.module-filter-group-nogap {
  display: flex;
  align-items: center;
}
.select-nogap {
  height: 32px;
  width: 90px;
  border-radius: 0 4px 4px 0;
  border: 1px solid #e6e6e6;
  border-left: none;
  box-sizing: border-box;
}
.date-filter-group-nogap {
  display: flex;
  align-items: center;
  flex-direction: row;
}
.sort-icons {
  display: inline-flex;
  flex-direction: column;
  margin-left: 4px;
  font-size: 12px;
  vertical-align: middle;
}
.triangle {
  color: #bbb;
  line-height: 10px;
  cursor: pointer;
  font-size: 12px;
  user-select: none;
}
.triangle.active {
  color: #1765ff;
  font-weight: bold;
}
@media (max-width: 1400px) {
  .main-card, .operation-log-card {
    max-width: 95vw;
  }
}
</style>
